<template>
  <view class="container">
    <view class="header">
      <text class="title">幸运转盘</text>
      <text class="subtitle">边缘刻度代表0-100%数值，彩色圆环为进度条，红色指针为当前选中值</text>
    </view>
    
    <!-- 转盘容器 -->
    <view class="wheel-container">
      <!-- Canvas 转盘 -->
      <canvas 
        canvas-id="wheelCanvas" 
        class="wheel-canvas"
        @touchstart="onCanvasTouchStart"
        @touchmove="onCanvasTouchMove"
        @touchend="onCanvasTouchEnd"
      ></canvas>
      
      <!-- 指针 -->
      <view 
        class="pointer" 
        :style="{ transform: `rotate(${pointerAngle}deg)`, transition: isSpinning ? 'transform 5s cubic-bezier(0.17, 0.67, 0.13, 0.99)' : 'none' }"
      >
        <view class="pointer-arrow"></view>
      </view>
      
      <!-- 当前选中值显示 -->
      <view class="selected-value" v-if="!isSpinning">
        <text>指针值: {{ currentValue.toFixed(1) }}%</text>
      </view>
    </view>
    
    <!-- 进度条百分比滑块控制 -->
    <view class="slider-container">
      <text class="slider-label">进度条数值: {{ progressValue }}%</text>
      <slider 
        v-model="progressValue" 
        min="0" 
        max="100" 
        step="0.5"
        @change="onProgressSliderChange"
        activeColor="#3498db"
        backgroundColor="#eaeaea"
        block-size="24"
        block-color="#3498db"
      ></slider>
    </view>
    
    <!-- 控制面板 -->
    <view class="control-panel">
      <view class="control-group">
        <text class="control-label">旋转圈数:</text>
        <input 
          type="number" 
          v-model="spinRounds" 
          min="1" 
          class="control-input"
          placeholder="输入圈数"
        >
        </input>
      </view>
      
      <view class="control-group">
        <text class="control-label">目标指针值:</text>
        <input 
          type="number" 
          v-model="targetValue" 
          min="0" 
          max="100"
          step="0.5"
          class="control-input"
          placeholder="0-100%"
        >
        </input>
      </view>
      
      <button 
        class="spin-button" 
        @click="startSpinning"
        :disabled="isSpinning"
      >
        {{ isSpinning ? '旋转中...' : '开始旋转' }}
      </button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      // 转盘和画布相关
      canvasWidth: 0,
      canvasHeight: 0,
      centerX: 0,
      centerY: 0,
      radius: 0,
      
      // 指针相关
      pointerAngle: 0,
      isSpinning: false,
      spinRounds: 3,
      targetValue: 0, // 指针目标数值(百分比)
      
      // 进度条相关
      progressValue: 0, // 进度条数值，由滑块控制
      currentValue: 0, // 当前指针指向的数值
      
      // 交互状态
      isDragging: false
    };
  },
  
  onLoad() {
    // 初始化画布
    this.initCanvas();
  },
  
  onReady() {
    // 绘制转盘
    this.drawWheel();
  },
  
  methods: {
    // 初始化画布
    initCanvas() {
      const query = uni.createSelectorQuery().in(this);
      query.select('.wheel-canvas')
        .boundingClientRect(data => {
          this.canvasWidth = data.width;
          this.canvasHeight = data.height;
          this.centerX = data.width / 2;
          this.centerY = data.height / 2;
          this.radius = Math.min(data.width, data.height) / 2 - 20;
          
          // 初始化绘制
          this.drawWheel();
        })
        .exec();
    },
    
    // 绘制转盘 - 包含独立的进度条和指针
    drawWheel() {
      if (!this.centerX || !this.centerY) return;
      
      const ctx = uni.createCanvasContext('wheelCanvas', this);
      
      // 清除画布
      ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
      
      // 绘制圆形背景
      ctx.beginPath();
      ctx.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI);
      ctx.setFillStyle('#f9f9f9');
      ctx.fill();
      
      // 绘制内部浅色圆环
      ctx.beginPath();
      ctx.arc(this.centerX, this.centerY, this.radius - 10, 0, 2 * Math.PI);
      ctx.setFillStyle('#ffffff');
      ctx.fill();
      
      // 绘制进度条圆环（从0%到进度条值）
      if (this.progressValue > 0) {
        const endAngle = (this.progressValue / 100) * 2 * Math.PI;
        ctx.beginPath();
        // 绘制一个稍宽的进度条圆弧
        ctx.arc(this.centerX, this.centerY, this.radius - 30, -Math.PI/2, endAngle - Math.PI/2);
        ctx.setLineWidth(20);
        ctx.setStrokeStyle('#3498db'); // 蓝色进度条
        ctx.stroke();
      }
      
      // 在中心显示进度条百分比
      ctx.setFontSize(36);
      ctx.setFillStyle('#34495e');
      ctx.setTextAlign('center');
      ctx.setTextBaseline('middle');
      ctx.fillText(`${this.progressValue.toFixed(1)}%`, this.centerX, this.centerY);
      
      // 绘制主刻度线和数值（每5%一个主刻度）
      const majorStep = 5; // 每5%一个主刻度
      for (let value = 0; value <= 100; value += majorStep) {
        const angle = (value / 100) * 360;
        const radians = angle * Math.PI / 180;
        
        // 主刻度线
        const lineLength = 15;
        const startX = this.centerX + (this.radius - lineLength) * Math.cos(radians);
        const startY = this.centerY + (this.radius - lineLength) * Math.sin(radians);
        const endX = this.centerX + this.radius * Math.cos(radians);
        const endY = this.centerY + this.radius * Math.sin(radians);
        
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.setLineWidth(3);
        ctx.setStrokeStyle('#3498db');
        ctx.stroke();
        
        // 绘制数值
        const textX = this.centerX + (this.radius - 30) * Math.cos(radians);
        const textY = this.centerY + (this.radius - 30) * Math.sin(radians);
        
        ctx.setFontSize(14);
        ctx.setFillStyle('#34495e');
        ctx.setTextAlign('center');
        ctx.setTextBaseline('middle');
        ctx.fillText(`${value}%`, textX, textY);
      }
      
      // 绘制次要刻度线（每1%一个次刻度）
      const minorStep = 1;
      for (let value = 0; value < 100; value += minorStep) {
        // 跳过主刻度的位置
        if (value % majorStep === 0) continue;
        
        const angle = (value / 100) * 360;
        const radians = angle * Math.PI / 180;
        
        // 次刻度线（比主刻度短）
        const lineLength = 8;
        const startX = this.centerX + (this.radius - lineLength) * Math.cos(radians);
        const startY = this.centerY + (this.radius - lineLength) * Math.sin(radians);
        const endX = this.centerX + this.radius * Math.cos(radians);
        const endY = this.centerY + this.radius * Math.sin(radians);
        
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.setLineWidth(2);
        ctx.setStrokeStyle('#bdc3c7');
        ctx.stroke();
      }
      
      // 绘制主圆圈描边
      ctx.beginPath();
      ctx.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI);
      ctx.setLineWidth(2);
      ctx.setStrokeStyle('#3498db');
      ctx.stroke();
      
      // 绘制中心圆
      ctx.beginPath();
      ctx.arc(this.centerX, this.centerY, 15, 0, 2 * Math.PI);
      ctx.setFillStyle('#e74c3c');
      ctx.fill();
      
      ctx.draw();
    },
    
    // 更新当前指针指向值
    updateCurrentValue() {
      // 计算指针角度对应的百分比值（0-100）
      let normalizedAngle = (this.pointerAngle % 360 + 360) % 360; // 确保角度在0-359之间
      this.currentValue = (normalizedAngle / 360) * 100;
    },
    
    // 开始旋转指针
    startSpinning() {
      if (this.isSpinning) return;
      
      // 验证输入
      if (!this.spinRounds || this.spinRounds < 1) {
        uni.showToast({ title: '请输入有效的旋转圈数', icon: 'none' });
        return;
      }
      
      if (this.targetValue === null || this.targetValue < 0 || this.targetValue > 100) {
        uni.showToast({ title: '请输入0-100之间的目标数值', icon: 'none' });
        return;
      }
      
      this.isSpinning = true;
      
      // 将目标数值转换为角度
      const targetAngle = (this.targetValue / 100) * 360;
      
      // 计算当前角度的归一化值（0-359）
      const currentNormalized = (this.pointerAngle % 360 + 360) % 360;
      
      // 计算需要旋转的角度，确保顺时针旋转
      let rotateAngle = this.spinRounds * 360;
      if (targetAngle >= currentNormalized) {
        rotateAngle += targetAngle - currentNormalized;
      } else {
        rotateAngle += (360 - currentNormalized) + targetAngle;
      }
      
      // 计算总旋转角度
      const totalAngle = this.pointerAngle + rotateAngle;
      
      // 触发旋转动画
      this.pointerAngle = totalAngle;
      
      // 动画结束后更新状态
      setTimeout(() => {
        this.isSpinning = false;
        this.updateCurrentValue();
      }, 5000); // 与CSS过渡时间一致
    },
    
    // 处理进度条滑块值变化
    onProgressSliderChange(e) {
      const value = e.detail.value;
      this.progressValue = value;
      this.drawWheel(); // 更新进度条显示
    },
    
    // 处理画布触摸开始
    onCanvasTouchStart(e) {
      if (this.isSpinning) return;
      
      const touch = e.touches[0];
      const touchX = touch.x;
      const touchY = touch.y;
      
      // 计算触摸点到中心的距离
      const dx = touchX - this.centerX;
      const dy = touchY - this.centerY;
      const distance = Math.sqrt(dx * dx + dy * dy);
      
      // 如果触摸在圆环附近，开始拖动指针
      if (distance > this.radius - 50 && distance < this.radius + 20) {
        this.isDragging = true;
        this.updatePointerFromTouch(touchX, touchY);
      }
    },
    
    // 处理画布触摸移动
    onCanvasTouchMove(e) {
      if (!this.isDragging || this.isSpinning) return;
      
      const touch = e.touches[0];
      this.updatePointerFromTouch(touch.x, touch.y);
    },
    
    // 处理画布触摸结束
    onCanvasTouchEnd() {
      this.isDragging = false;
    },
    
    // 根据触摸位置更新指针
    updatePointerFromTouch(x, y) {
      // 计算触摸点相对于中心的角度
      let angle = Math.atan2(y - this.centerY, x - this.centerX) * 180 / Math.PI;
      angle = (angle + 360) % 360; // 转换为0-360度
      
      // 更新指针角度
      this.pointerAngle = angle;
      
      // 更新数值
      this.updateCurrentValue();
    }
  },
  
  watch: {
    // 当指针角度变化时更新当前值
    pointerAngle() {
      if (!this.isSpinning) {
        this.updateCurrentValue();
      }
    },
    // 当进度条值变化时重绘
    progressValue() {
      this.drawWheel();
    }
  }
};
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #f9f9f9;
  min-height: 100vh;
  padding: 20rpx;
}

.header {
  text-align: center;
  margin: 30rpx 0 50rpx;
}

.title {
  font-size: 36rpx;
  font-weight: bold;
  color: #333;
  margin-bottom: 10rpx;
  display: block;
}

.subtitle {
  font-size: 24rpx;
  color: #666;
}

.wheel-container {
  position: relative;
  width: 600rpx;
  height: 600rpx;
  margin-bottom: 30rpx;
}

.wheel-canvas {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
}

.pointer {
  position: absolute;
  top: -30rpx;
  left: 50%;
  transform-origin: center 330rpx; /* 指针旋转中心在转盘中心 */
  width: 30rpx;
  height: 300rpx;
  margin-left: -15rpx;
  z-index: 10;
}

.pointer-arrow {
  width: 0;
  height: 0;
  border-left: 15rpx solid transparent;
  border-right: 15rpx solid transparent;
  border-top: 40rpx solid #e74c3c; /* 指针颜色 */
  position: absolute;
  top: 0;
  left: 0;
}

/* 当前选中值显示 */
.selected-value {
  position: absolute;
  bottom: -40rpx;
  left: 50%;
  transform: translateX(-50%);
  background-color: #e74c3c; /* 与指针同色 */
  color: white;
  padding: 8rpx 20rpx;
  border-radius: 20rpx;
  font-size: 26rpx;
  font-weight: bold;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.2);
}

/* 滑块样式 */
.slider-container {
  width: 500rpx;
  margin-bottom: 40rpx;
  padding: 0 20rpx;
}

.slider-label {
  display: block;
  font-size: 26rpx;
  color: #555;
  margin-bottom: 15rpx;
  text-align: center;
}

.control-panel {
  width: 500rpx;
  background-color: white;
  border-radius: 20rpx;
  padding: 30rpx;
  box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.05);
}

.control-group {
  display: flex;
  align-items: center;
  margin-bottom: 25rpx;
}

.control-label {
  font-size: 26rpx;
  color: #555;
  width: 180rpx;
}

.control-input {
  flex: 1;
  height: 60rpx;
  border: 2rpx solid #ddd;
  border-radius: 8rpx;
  padding: 0 15rpx;
  font-size: 26rpx;
}

.spin-button {
  width: 100%;
  height: 80rpx;
  line-height: 80rpx;
  background-color: #3498db;
  color: white;
  font-size: 28rpx;
  border-radius: 10rpx;
  margin: 10rpx 0 30rpx;
  transition: background-color 0.3s;
}

.spin-button:hover {
  background-color: #2980b9;
}

.spin-button:disabled {
  background-color: #bdc3c7;
  opacity: 0.8;
}
</style>